import java.awt.*;
import java.io.*;
import java.util.*;
import java.util.List;

import javax.script.*;

public class Verden extends Observable implements Serializable  {
	public Image baggrund;

	private void getFigurer(ArrayList<Integer> a, int i, ArrayList<Integer> fx, ArrayList<Integer> fy, Figur parent) {
		if (a.isEmpty())
			return;
		String str = "$model.getFigur(" + i + ").";
		for(int j = 0; j < a.size() - 1; j++)
			str += "led.values[" + a.get(j) + "].del.";
		String str2 = str + "led.values[" + a.get(a.size() - 1) + "].del.";
		Figur f;
		
		try {
			f = new Figur();
			int opx = ((Long)rubyEngine.eval(str + "led.values[" + a.get(a.size() - 1) + "].opx")).intValue();
			int opy = ((Long)rubyEngine.eval(str + "led.values[" + a.get(a.size() - 1) + "].opy")).intValue();
			f.x = fx.get(fx.size() - 1)
			+ opx
			- ((Long)rubyEngine.eval(str + "led.values[" + a.get(a.size() - 1) + "].nedx")).intValue();
			f.y = fy.get(fy.size() - 1)
			+ opy
			- ((Long)rubyEngine.eval(str + "led.values[" + a.get(a.size() - 1) + "].nedy")).intValue();
			String str3 = (String)rubyEngine.eval(str2 + "billede");
			f.billede = ImageDB.images.get(str3);
			f.rotation = ((Long)rubyEngine.eval(str2 + "rotation")).intValue();
			f.centerx = fx.get(fx.size() - 1) + opx;
			f.centery = fy.get(fy.size() - 1) + opy;
			f.parent = parent;
			parent.child.add(f);

			int length = ((Long)rubyEngine.eval(str2 + "led.length")).intValue();
			if (length == 0) {
				int length2 = ((Long)rubyEngine.eval(str + "led.length")).intValue();
				if(length2 - 1 == a.get(a.size() - 1)) {
					a.remove(a.size() - 1);
					if(!a.isEmpty()) {
						fx.remove(fx.size() - 1);
						fy.remove(fy.size() - 1);
						parent = parent.parent;
					}
				}
				else {
					a.set(a.size() - 1, a.get(a.size() - 1) + 1);
				}
			}
			else {
				a.add(0);
				fx.add(f.x);
				fy.add(f.y);
				parent = f;
			}
		} catch (ScriptException e) {
			e.printStackTrace();
			return;
		} catch (ClassCastException e) {
			e.printStackTrace();
			return;
		}
		getFigurer(a, i, fx, fy, parent);
	}

	public ArrayList<Figur> getFigur() {
		ArrayList<Figur> figurer = new ArrayList<Figur>();
		try {
			Long antal = (Long)rubyEngine.eval("$model.getAntalFigurer");
			for(int i=0;i<antal;i++) {
				Figur f = new Figur();
				f.navn = (String)rubyEngine.eval("$model.getFigur(" + i + ").navn");
				f.x = ((Long)rubyEngine.eval("$model.getFigur(" + i + ").x")).intValue();
				f.y = ((Long)rubyEngine.eval("$model.getFigur(" + i + ").y")).intValue();
				String str = (String)rubyEngine.eval("$model.getFigur(" + i + ").billede");
				f.billede = ImageDB.images.get(str);
				f.centerx = f.x + (f.billede.getWidth(null) / 2);
				f.centery = f.y + (f.billede.getHeight(null) / 2);
				f.rotation = ((Long)rubyEngine.eval("$model.getFigur(" + i + ").rotation")).intValue();
				int length = ((Long)rubyEngine.eval("$model.getFigur(" + i + ").led.length")).intValue();
				figurer.add(f);
				if (length > 0) {
					ArrayList<Integer> a = new ArrayList<Integer>();
					a.add(0);
					ArrayList<Integer> fx = new ArrayList<Integer>();
					fx.add(f.x);
					ArrayList<Integer> fy = new ArrayList<Integer>();
					fy.add(f.y);
					getFigurer(a, i, fx, fy, f);
				}
			}
			return(figurer);
		} catch (ScriptException e) {
			e.printStackTrace();
			return(null);
		} catch (ClassCastException e) {
			e.printStackTrace();
			return(null);
		}
	}
	private String script[] = {};
	private int line;
	private ArrayList<String> nextBlock;
	private ScriptEngineManager mgr;
	private ScriptEngine rubyEngine;
	private Timer timer;

	public void setBaggrund(Image baggrund) {
		this.baggrund = baggrund;
	}

	class Tid extends TimerTask {
		public void run() {
			animate();
		}
	}
	
	public void setScript(ArrayList<String> script) {
		String a[] = {};
		this.script = script.toArray(a);
	}

	public void reset () {
	}
	
	public Verden (String prescript) {
		nextBlock = new ArrayList<String>();
		line = 0;
		mgr = new ScriptEngineManager();
		List<ScriptEngineFactory> list = mgr.getEngineFactories();
		for (ScriptEngineFactory f : list) {
			System.out.println(f.getEngineName());
		}
		rubyEngine = mgr.getEngineByName("jruby");
			
		try {
			rubyEngine.eval(new BufferedReader(new FileReader(Main.srcPath + "common_script.rb"))); //changed from common2.rb

			rubyEngine.eval(prescript);
		} catch (ScriptException ex) {
			ex.printStackTrace();
			System.exit(-1);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.exit(-1);
		}
	}

	public void startAnimation () {
		// New Tid Timer
	    timer = new Timer();
	    timer.scheduleAtFixedRate(new Tid(), 0, 30);
	}

	public void stopAnimation () {
		// Stop Tid Timer
        timer.cancel();
	}

	public void animate() {
		if (nextBlock.size() ==  0) {
			if(script.length == line) {
				stopAnimation();
				setChanged();
				notifyObservers(Boolean.FALSE);
				return;
			}
			if(script[line] == "") {
				line++;
				animate();
				return;
			}
			if(script[line].compareToIgnoreCase("begynd blok") == 0) {
				line++;
				while(script[line].compareToIgnoreCase("slut blok") != 0 && line < script.length) {
					nextBlock.add(script[line]);
					line++;
				}
				line++;
			}
			else {
				nextBlock.add(script[line]);
				line++;
			}
		}
		for (int i = 0; i < nextBlock.size(); i++) {
			String nextLine = nextBlock.get(i);
			Object o = null;
			try {
				o = rubyEngine.eval(nextLine);
			} catch  (ScriptException ex) {
				ex.printStackTrace();
				stopAnimation();
				setChanged();
				notifyObservers(Boolean.FALSE);
				return;
			}
			try {
				if(o == null || (Boolean) o) {
					nextBlock.remove(i);
					i--;
				}
			} catch (ClassCastException e) {
				nextBlock.remove(i);
				i--;
			}
		}
		setChanged();
		notifyObservers();
	}
}
